/*
 * @Author: hanxusheng
 * @Date: 2019-07-11 13:48:07
 * @Last Modified by: maxx
 * @Last Modified time: 2020-03-26 10:36:45
 */

// 格式化日期--扩展原型
export const formatTime = function (time, fmt) {
  if (!time) return ''
  let _this = new Date(time)
  let o = {
    'M+': _this.getMonth() + 1, // 月份
    'd+': _this.getDate(), // 日
    'h+': _this.getHours(), // 小时
    'm+': _this.getMinutes(), // 分
    's+': _this.getSeconds(), // 秒
    'q+': Math.floor((_this.getMonth() + 3) / 3), // 季度
    'S': _this.getMilliseconds() // 毫秒
  }
  if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (_this.getFullYear() + '').substr(4 - RegExp.$1.length))
  for (let k in o) {
    if (new RegExp('(' + k + ')').test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
  }
  return fmt
}

export const typeOf = (() => {
  const map = {
    '[object Boolean]': 'boolean',
    '[object Number]': 'number',
    '[object String]': 'string',
    '[object Function]': 'function',
    '[object Array]': 'array',
    '[object Date]': 'date',
    '[object RegExp]': 'regExp',
    '[object Undefined]': 'undefined',
    '[object Null]': 'null',
    '[object Object]': 'object'
  }
  const toString = Object.prototype.toString
  return obj => {
    return map[toString.call(obj)]
  }
})()

/**
 * 深拷贝/继承
 * @returns [true|target,source1.....]
 * ex: extend(true,obj1) deepCopy一份obj1
 *     extend(true,target,onj1,obj2...) 将所有的obj1,obj2...集合到target
 */
export const extend = (() => {
  const isPlainObject = (() => {
    var class2type = {}

    var hasOwn = class2type.hasOwnProperty

    var fnToString = hasOwn.toString

    var ObjectFunctionString = fnToString.call(Object)

    var getProto = Object.getPrototypeOf

    return (obj) => {
      var proto, Ctor
      // Detect obvious negatives
      // Use toString instead of jQuery.type to catch host objects
      if (!obj || toString.call(obj) !== '[object Object]') {
        return false
      }

      proto = getProto(obj)

      // Objects with no prototype (e.g., `Object.create( null )`) are plain
      if (!proto) {
        return true
      }

      // Objects with prototype are plain iff they were constructed by a global Object function
      Ctor = hasOwn.call(proto, 'constructor') && proto.constructor
      return typeof Ctor === 'function' && fnToString.call(Ctor) === ObjectFunctionString
    }
  })()

  const extend = (...arg) => {
    let options
    let name
    let src
    let copy
    let copyIsArray
    let clone
    let target = arg[0] || {}
    let i = 1
    let length = arg.length
    let deep = false

    // Handle a deep copy situation
    if (typeof target === 'boolean') {
      deep = target

      // Skip the boolean and the target
      target = arg[i] || {}
      i++
    }

    // Handle case when target is a string or something (possible in deep copy)
    if (typeof target !== 'object' && !typeOf(target) === 'function') {
      target = {}
    }

    // Extend jQuery itself if only one argument is passed
    if (i === length) {
      i--
      target = Array.isArray(arg[i]) ? [] : {}
    }

    for (; i < length; i++) {
      // Only deal with non-null/undefined values
      if ((options = arg[i]) != null) {
        // Extend the base object
        for (name in options) {
          src = target[name]
          copy = options[name]

          // Prevent never-ending loop
          if (target === copy) {
            continue
          }

          // Recurse if we're merging plain objects or arrays
          if (deep && copy && (isPlainObject(copy) ||
            (copyIsArray = Array.isArray(copy)))) {
            if (copyIsArray) {
              copyIsArray = false
              clone = src && Array.isArray(src) ? src : []
            } else {
              clone = src && isPlainObject(src) ? src : {}
            }

            // Never move original objects, clone them
            target[name] = extend(deep, clone, copy)

            // Don't bring in undefined values
          } else if (copy !== undefined) {
            target[name] = copy
          }
        }
      }
    }
    return target
  }

  return extend
})()

// 遇到相同元素级属性，以（minor）为准 返回新的Object
export const mergeJSON = (target, ...values) => {
  const merge = (minor, main) => {
    for (var key in main) {
      if (minor[key] === undefined) { // 不冲突的，直接赋值
        minor[key] = main[key]
        continue
      }
      if (typeOf(minor[key]) === 'object' && typeOf(main[key]) === 'object') {
        // 冲突了，如果是Object，看看有么有不冲突的属性
        merge(minor[key], main[key])
      } else if (typeOf(minor[key]) === 'array') {
        minor[key] = minor[key].concat(main[key])
      } else {
        minor[key] = main[key]
      }
    }
  }
  const minor = extend(true, target)
  values.forEach(main => {
    merge(minor, main)
  })

  return minor
}

/* 函数防抖
 * @param {*} fn 回调函数
 * @param {*} delay 延时间隔
 * @param {*} mustRunDelay 最大间隔，时间达到最大间隔时会执行
 */
export const debounce = (fn, delay, mustRunDelay) => {
  let timer
  let tStart
  return function () {
    return new Promise((resolve) => {
      let context = this
      let args = arguments
      let tCurr = +new Date()
      clearTimeout(timer || 0)
      if (!tStart) {
        tStart = tCurr
      }
      if (tCurr - tStart >= mustRunDelay) {
        const data = fn.apply(context, args)
        resolve(data)
        tStart = tCurr
      } else {
        timer = setTimeout(function () {
          const data = fn.apply(context, args)
          resolve(data)
        }, delay)
      }
    })
  }
}

/**
 * 加密处理
 */
// export const encryption = (params) => {
//   let {
//     data,
//     type,
//     param,
//     key
//   } = params
//   let result = JSON.parse(JSON.stringify(data))
//   if (type === 'Base64') {
//     param.forEach(ele => {
//       result[ele] = btoa(result[ele])
//     })
//   } else {
//     param.forEach(ele => {
//       var data = result[ele]
//       key = CryptoJS.enc.Latin1.parse(key)
//       var iv = key
//       // 加密
//       var encrypted = CryptoJS.AES.encrypt(
//         data,
//         key,
//         { iv: iv,
//           mode: CryptoJS.mode.CBC,
//           padding: CryptoJS.pad.ZeroPadding
//         })
//       result[ele] = encrypted.toString()
//     })
//   }
//   return result
// }

// 生成hash值
export const createHash = function (hashLength) {
  if (!hashLength || typeof (Number(hashLength)) !== 'number') {
    return
  }
  var ar = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
  var hs = []
  var hl = Number(hashLength)
  var al = ar.length
  for (var i = 0; i < hl; i++) {
    hs.push(ar[Math.floor(Math.random() * al)])
  }
  return 'D3' + hs.join('')
}

//表单序列化
export const serialize = data => {
  let list = [];
  Object.keys(data).forEach(ele => {
    list.push(`${ele}=${data[ele]}`)
  })
  return list.join('&');
};

// 数字每三位加逗号
export const format_number = function (n) {
  var b = Number(n).toString();
  var len = b.length;
  if (len <= 3) {
    return b;
  }
  var r = len % 3;
  return r > 0 ? b.slice(0, r) + "," + b.slice(r, len).match(/\d{3}/g).join(",") : b.slice(r, len).match(/\d{3}/g).join(",");
}

// 输入框获得焦点 页面会被顶上去
export const blur = function () {
  setTimeout(function () {
    var scrollHeight = document.documentElement.scrollTop || document.body.scrollTop || 0
    window.scrollTo(0, Math.max(scrollHeight - 1, 0))
  }, 100)
}

// 截取链接上面的值 不带#号
export const getRequest = function () {
  var url = window.location.search; //获取url中"?"符后的字串
  var theRequest = new Object();
  if (url.indexOf("?") != -1) {
    var str = url.substr(1);
    var strs = str.split("&");
    for (var i = 0; i < strs.length; i++) {
      theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
    }
  }
  return theRequest;
}
//截取链接上面的值 带#号的链接
export const getQueryString = function (name) {
  let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
  if (window.location.href.split("#/")[0].indexOf("?") < 0) {
    return null;
  }
  let r = window.location.href.split("#/")[0].split("?")[1].match(reg);
  if (r != null) return decodeURIComponent(r[2]);
  return null;
}
// 判断需要的值不为空
export const isEmpty = function (v) {
  switch (typeof v) {
    case 'undefined':
      return true;
    case 'string':
      if (v.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true;
      break;
    case 'boolean':
      if (!v) return true;
      break;
    case 'number':
      if (0 === v || isNaN(v)) return true;
      break;
    case 'object':
      if (null === v || v.length === 0) return true;
      for (var i in v) {
        return false;
      }
      return true;
  }
  return false;
}
// 秒转分钟秒
export const s_to_hms = function (value) {
  let result = parseInt(value)
  let h = Math.floor(result / 3600) < 10 ? '0' + Math.floor(result / 3600) : Math.floor(result / 3600)
  let m = Math.floor((result / 60 % 60)) < 10 ? '0' + Math.floor((result / 60 % 60)) : Math.floor((result / 60 % 60))
  let s = Math.floor((result % 60)) < 10 ? '0' + Math.floor((result % 60)) : Math.floor((result % 60))
  result = `${h}小时${m}分钟${s}秒`
  return result
}
